﻿#include "DragonInfo.h"
#include "../Settings.h"

using namespace Server::MirEnvir;

namespace Server::MirDatabase
{

    Server::MirEnvir::Envir *DragonInfo::getEnvir()
    {
        return Envir::getMain();
    }

    Server::MessageQueue *DragonInfo::getMessageQueue()
    {
        return MessageQueue::getInstance();
    }

    DragonInfo::DragonInfo()
    {
        //Default values
        Enabled = false;
        MapFileName = "D2083";
        MonsterName = "Evil Mir";
        BodyName = "00";
        Location = new Point(82, 44);
        DropAreaTop = new Point(75, 45);
        DropAreaBottom = new Point(86, 57);

        Level = 1;

        for (int i = 0; i < Exps.size(); i++)
        {
            Exps[i] = (i + 1) * 10000;
        }
        for (int i = 0; i < Drops.size(); i++)
        {
            Drops[i] = std::vector<DropInfo*>();
        }
    }

    DragonInfo::DragonInfo(BinaryReader *reader)
    {
        Enabled = reader->ReadBoolean();
        MapFileName = reader->ReadString();
        MonsterName = reader->ReadString();
        BodyName = reader->ReadString();
        Location = new Point(reader->ReadInt32(), reader->ReadInt32());
        DropAreaTop = new Point(reader->ReadInt32(), reader->ReadInt32());
        DropAreaBottom = new Point(reader->ReadInt32(), reader->ReadInt32());

        Level = 1;

        for (int i = 0; i < Exps.size(); i++)
        {
            Exps[i] = reader->ReadInt64();
        }
        for (int i = 0; i < Drops.size(); i++)
        {
            Drops[i] = std::vector<DropInfo*>();
        }
    }

    void DragonInfo::Save(BinaryWriter *writer)
    {
        writer->Write(Enabled);
        writer->Write(MapFileName);
        writer->Write(MonsterName);
        writer->Write(BodyName);
        writer->Write(Location->X);
        writer->Write(Location->Y);
        writer->Write(DropAreaTop->X);
        writer->Write(DropAreaTop->Y);
        writer->Write(DropAreaBottom->X);
        writer->Write(DropAreaBottom->Y);
        for (int i = 0; i < Exps.size(); i++)
        {
            writer->Write(Exps[i]);
        }
    }

    void DragonInfo::LoadDrops()
    {
        for (int i = 0; i < Globals::MaxDragonLevel; i++)
        {
            Drops[i].clear();
        }
        std::string path = FileSystem::combine(Settings::DropPath, "DragonItem.txt");
        if (!FileSystem::fileExists(path))
        {
            std::vector<std::string> contents = {";Pots + Other", "", "", ";Weapons", "", "", ";Armour", "", "", ";Helmets", "", "", ";Necklace", "", "", ";Bracelets", "", "", ";Rings", "", "", ";Shoes", "", "", ";Belts", "", "", ";Stone"};

            File::WriteAllLines(path, contents);


            return;
        }

        std::vector<std::string> lines = File::ReadAllLines(path);

        for (int i = 0; i < lines.size(); i++)
        {
            if (StringHelper::startsWith(lines[i], ";") || StringHelper::isEmptyOrWhiteSpace(lines[i]))
            {
                continue;
            }

            DropInfo *drop = DropInfo::FromLine(lines[i]);
            if (drop == nullptr)
            {
                getMessageQueue()->Enqueue(StringHelper::formatSimple("Could not load Drop: DragonItem, Line {0}", lines[i]));
                continue;
            }

            if (drop->level <= 0 || drop->level > Globals::MaxDragonLevel)
            {
                return;
            }
            Drops[drop->level - 1].push_back(drop);
        }

        for (int i = 0; i < Globals::MaxDragonLevel; i++)
        {
//C# TO C++ CONVERTER TODO TASK: The 'Compare' parameter of std::sort produces a boolean value, while the .NET Comparison parameter produces a tri-state result:
//ORIGINAL LINE: Drops[i].Sort((drop1, drop2) =>
            std::sort(Drops[i].begin(), Drops[i].end(), [&] (drop1, drop2)
            {
                if (drop1::Gold > 0 && drop2->Gold == 0)
                {
                    return 1;
                }
                if (drop1->Gold == 0 && drop2::Gold > 0)
                {
                    return -1;
                }
    
                return drop1::Item->Type->CompareTo(drop2::Item->Type);
            });
        }
    }

    DragonInfo::DropInfo *DragonInfo::DropInfo::FromLine(const std::string &s)
    {
        std::vector<std::string> parts = s.Split({' '}, StringSplitOptions::RemoveEmptyEntries);

        DropInfo *info = new DropInfo();

        if (!int::TryParse(parts[0].substr(2), info->Chance))
        {
            delete info;
            return nullptr;
        }
//C# TO C++ CONVERTER TODO TASK: The following System.String compare method is not converted:
        if (std::string::Compare(parts[1], "Gold", StringComparison::OrdinalIgnoreCase) == 0)
        {
            if (parts.size() < 4)
            {
                delete info;
                return nullptr;
            }
            if (!unsigned int::TryParse(parts[2], info->Gold) || info->Gold == 0)
            {
                delete info;
                return nullptr;
            }
            if (!unsigned char::TryParse(parts[3], info->level))
            {
                delete info;
                return nullptr;
            }
        }
        else
        {
            if (parts.size() < 3)
            {
                delete info;
                return nullptr;
            }
            info->Item = getEnvir()->GetItemInfo(parts[1]);
            if (info->Item == nullptr)
            {
                delete info;
                return nullptr;
            }
            if (!unsigned char::TryParse(parts[2], info->level))
            {
                delete info;
                return nullptr;
            }
        }

//C# TO C++ CONVERTER TODO TASK: A 'delete info' statement was not added since info was used in a 'return' or 'throw' statement.
        return info;
    }
}
